/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package coalescent.model;

import commons.core.Singletons;
import commons.util.ExceptionUtil;

import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * This model was first proposed by Kimura and Crow (1964, Genetics) and popularly known as infinite
 * alleles model. This model defines two population genetic events namely, coalescent and
 * mutation.<p/>
 * The following is the specification of the model. <ul> <li> Panmictic population <li> Mutations
 * create new alleles (not existing in the current population nor in the previous ones) <li> Alleles
 * are selectively neutral <li> Genes are passed from parents to offsprings exactly (e.g., no
 * recombination is present) </ul>
 *
 * @author Susanta Tewari
 * @version 1.3.0
 */
public class KC64 extends PopGenModel<KC64.EventType> {

    /** Field description */
    private final double mutationRate;

    /**
     * Initializes the mutation parameter.
     *
     * @param mutationRate scaled mutation rate
     * @throws IllegalArgumentException if, <ol> <li>{@code mutationRate} &lt 0</li></ol>
     */
    public KC64(double mutationRate) {

        super(EventType.class);

        if (mutationRate < 0) {

            ExceptionUtil.throwIllegalArgEx(getClass(), "Mutation_Parameter_Negative",
                                            mutationRate);
        }

        this.mutationRate = mutationRate;
    }

    /**
     * Population genetic events under this model. It includes coalescent and mutation events.
     */
    public static enum EventType {

        /**
         * Coalescent event.
         */
        COALESCENT {

            /**
             * Abbreviation code for this event.
             *
             * @return abbreviation code C
             */
            @Override
            public String toString() {
                return "C";
            }
        },

        /**
         * Mutation event type.
         */
        MUTATION {

            /**
             * Abbreviation code for this event.
             *
             * @return abbreviation code M
             */
            @Override
            public String toString() {
                return "M";
            }
        }
    }

    /**
     * Scaled mutation rate of the model.
     *
     * @return scaled mutation rate
     */
    public final double getMutationRate() {
        return mutationRate;
    }

    /**
     * Contains information on event types and mutation parameter.
     *
     * @return information on event types and mutation parameter
     */
    @Override
    public String toString() {

        return new ToStringBuilder(this, Singletons.TO_STRING_STYLE).appendSuper(
            super.toString()).append("mutation-rate", mutationRate).toString();
    }
}
